package cn.cloudplug.core.net;

import android.content.Context;



import java.io.File;
import java.util.LinkedHashMap;

import cn.cloudplug.core.net.callback.IError;
import cn.cloudplug.core.net.callback.IFailure;
import cn.cloudplug.core.net.callback.IRequest;
import cn.cloudplug.core.net.callback.ISuccess;
import cn.cloudplug.core.net.callback.RequestCallbacks;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;

/**
 * Created by Watt on 2017/12/19.
 */

public class RestClient {
    private final LinkedHashMap<String, Object> params;
    private final String url;
    private final String download_dir;
    private final String extension;
    private final String name;
    private final IRequest request;
    private final ISuccess success;
    private final IFailure failure;
    private final IError error;
    private final RequestBody requestBody;
    private final File file;
    private final Context context;

    public RestClient(LinkedHashMap<String, Object> params, String url, IRequest request, String download_dir, String extension, String name, ISuccess success, IFailure failure, IError error, RequestBody requestBody, File file, Context context) {
        this.params = params;
        this.url = url;
        this.request = request;
        this.download_dir = download_dir;
        this.extension = extension;
        this.name = name;
        this.success = success;
        this.failure = failure;
        this.error = error;
        this.requestBody = requestBody;
        this.file = file;
        this.context = context;
    }

    public void request(HttpMethod method){
        final RestService service = RestCreator.getRestService();
        Call<String> call=null;
        if(request!=null){
            request.onStart();
        }
        switch (method){
            case GET:
                call = service.get(url, params);
                break;
            case POST:
                call = service.post(url, params);
                break;
            case POST_RAW:
                call = service.postRaw(url, requestBody);
                break;
            case PUT:
                call = service.put(url, params);
                break;
            case PUT_RAW:
                call = service.putRaw(url, requestBody);
                break;
            case DELETE:
                call = service.delete(url, params);
                break;
            case UPLOAD:
                final RequestBody requestBody =
                        RequestBody.create(MediaType.parse(MultipartBody.FORM.toString()), file);
                final MultipartBody.Part body =
                        MultipartBody.Part.createFormData("file", file.getName(), requestBody);
                call = service.upload(url, body);
                break;
            default:
                break;
        }
        if (call!=null)
            call.enqueue(getRequestCallbacks());
    }

    public void get(){
        request(HttpMethod.GET);
    }

    public void post(){
        if(requestBody!=null){
            if(!params.isEmpty())throw new RuntimeException("params must be null!");
            request(HttpMethod.POST_RAW);
        }else
        request(HttpMethod.POST);
    }

    public void put(){
        if(requestBody!=null){
            if(!params.isEmpty())throw new RuntimeException("params must be null!");
            request(HttpMethod.PUT_RAW);
        }else request(HttpMethod.PUT);

    }

    public void delete(){
        request(HttpMethod.DELETE);
    }

    private RequestCallbacks getRequestCallbacks(){
        return new RequestCallbacks(request,success,failure,error);
    }

    public static Builder builder(){
        return new Builder();
    }

    public static class Builder{
        public RestClient build(){
            return new RestClient(params,url,request,download_dir,extension,name,success,failure,error,requestBody,file,context);
        }
        private LinkedHashMap<String, Object> params=new LinkedHashMap<>();
        private String url;
        private IRequest request;
        private String download_dir;
        private String extension;
        private String name;
        private ISuccess success;
        private IFailure failure;
        private IError error;
        private RequestBody requestBody;
        private File file;
        private Context context;

        public LinkedHashMap<String, Object> getParams() {
            return params;
        }

        public Builder params(LinkedHashMap<String, Object> params) {
            this.params.putAll(params);
            return this;
        }

        public Builder params(String key, Object value) {
            if (params==null){
                params=new LinkedHashMap<>();
            }
            this.params.put(key, value);
            return this;
        }

        public String getUrl() {
            return url;
        }

        public Builder url(String url) {
            this.url = url;
            return this;
        }

        public IRequest getRequest() {
            return request;
        }

        public Builder request(IRequest request) {
            this.request = request;
            return this;
        }

        public String getDir() {
            return download_dir;
        }

        public Builder dir(String download_dir) {
            this.download_dir = download_dir;
            return this;
        }

        public String getExtension() {
            return extension;
        }

        public Builder extension(String extension) {
            this.extension = extension;
            return this;
        }

        public String getName() {
            return name;
        }

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public ISuccess getSuccess() {
            return success;
        }

        public Builder success(ISuccess success) {
            this.success = success;
            return this;
        }

        public IFailure getFailure() {
            return failure;
        }

        public Builder failure(IFailure failure) {
            this.failure = failure;
            return this;
        }

        public IError getError() {
            return error;
        }

        public Builder error(IError error) {
            this.error = error;
            return this;
        }

        public RequestBody getRequestBody() {
            return requestBody;
        }

        public Builder requestBody(RequestBody requestBody) {
            this.requestBody = requestBody;
            return this;
        }

        public File getFile() {
            return file;
        }

        public Builder file(File file) {
            this.file = file;
            return this;
        }

        public Context getContext() {
            return context;
        }

        public Builder context(Context context) {
            this.context = context;
            return this;
        }
    }
}
